import { _decorator, Component, Node, Vec3, PhysicsSystem2D, physics, Collider2D, Vec2 } from 'cc';
import { QuadTreeNode, Bounds } from './QuadTreeNode';
import { VisionObstacle } from './VisionObstacle';

const { ccclass, property } = _decorator;

/**
 * 障碍物管理器
 * 
 * 功能：
 * 1. 管理所有视野障碍物
 * 2. 处理障碍物的碰撞检测
 * 3. 提供视线阻挡查询
 * 4. 优化空间查询性能
 * 
 * 特点：
 * 1. 空间分区优化
 * 2. 动态障碍物支持
 * 3. 射线检测系统
 * 4. 缓存查询结果
 */
@ccclass('ObstacleManager')
export class ObstacleManager extends Component {
    private static _instance: ObstacleManager | null = null;
    private quadTree: QuadTreeNode | null = null;
    private obstacles: Set<Node> = new Set();

    @property
    private worldSize: number = 100;

    @property
    private maxObjectsPerNode: number = 10;

    @property
    private maxLevels: number = 5;

    @property
    private raycastMask: number = 0b100000; // 使用第6位作为视线检测层级

    public static get instance(): ObstacleManager {
        return this._instance!;
    }

    onLoad() {
        if (ObstacleManager._instance === null) {
            ObstacleManager._instance = this;
            this.initPhysics();
            this.initQuadTree();
        } else {
            this.node.destroy();
        }
    }

    private initPhysics() {
        // 启用物理系统
        PhysicsSystem2D.instance.enable = true;
    }

    private initQuadTree() {
        const bounds: Bounds = {
            x: -this.worldSize / 2,
            y: -this.worldSize / 2,
            width: this.worldSize,
            height: this.worldSize
        };
        this.quadTree = new QuadTreeNode(bounds, this.maxObjectsPerNode, this.maxLevels);
    }

    public addObstacle(obstacle: Node) {
        this.obstacles.add(obstacle);
        this.quadTree?.insert(obstacle);

        // 设置物理碰撞组
        const collider = obstacle.getComponent(Collider2D);
        if (collider) {
            physics.setCollisionGroup(obstacle, this.raycastMask);
            collider.enabled = true;
        }
    }

    public removeObstacle(obstacle: Node) {
        this.obstacles.delete(obstacle);
        // 重建四叉树
        this.rebuildQuadTree();
    }

    private rebuildQuadTree() {
        this.quadTree?.clear();
        for (const obstacle of this.obstacles) {
            this.quadTree?.insert(obstacle);
        }
    }

    public hasLineOfSight(from: Vec3, to: Vec3): boolean {
        // 获取射线路径上的潜在障碍物
        const bounds = this.getRayBounds(from, to);
        const potentialObstacles = this.quadTree?.retrieve(bounds) || [];

        // 转换为2D坐标进行射线检测
        const start = new Vec2(from.x, from.z);
        const end = new Vec2(to.x, to.z);

        // 获取所有碰撞器
        const colliders = potentialObstacles
            .map(obj => obj.getComponent(Collider2D))
            .filter(collider => collider !== null) as Collider2D[];

        // 进行射线检测
        const results = PhysicsSystem2D.instance.raycast(
            start,
            end,
            this.raycastMask,
            colliders
        );

        if (results.length === 0) {
            return true; // 无遮挡
        }

        // 计算视线阻挡程度
        let totalBlockFactor = 1.0;
        for (const result of results) {
            const obstacle = result.collider.getComponent(VisionObstacle);
            if (obstacle) {
                totalBlockFactor *= (1 - obstacle.getBlockFactor());
            }
        }

        // 如果阻挡度超过阈值，则视为视线被阻挡
        return totalBlockFactor > 0.1;
    }

    public getClosestObstacle(position: Vec3, maxDistance: number): Node | null {
        const searchBounds: Bounds = {
            x: position.x - maxDistance,
            y: position.z - maxDistance,
            width: maxDistance * 2,
            height: maxDistance * 2
        };

        const potentialObstacles = this.quadTree?.retrieve(searchBounds) || [];
        let closest: Node | null = null;
        let minDistance = maxDistance;

        for (const obstacle of potentialObstacles) {
            const distance = Vec3.distance(position, obstacle.position);
            if (distance < minDistance) {
                minDistance = distance;
                closest = obstacle;
            }
        }

        return closest;
    }

    private getRayBounds(from: Vec3, to: Vec3): Bounds {
        const minX = Math.min(from.x, to.x);
        const maxX = Math.max(from.x, to.x);
        const minY = Math.min(from.z, to.z);
        const maxY = Math.max(from.z, to.z);

        return {
            x: minX,
            y: minY,
            width: maxX - minX,
            height: maxY - minY
        };
    }

    update() {
        // 如果障碍物可以移动，每帧更新四叉树
        if (this.hasMovingObstacles()) {
            this.rebuildQuadTree();
        }
    }

    private hasMovingObstacles(): boolean {
        // 检查是否有移动的障碍物
        // 可以通过缓存上一帧的位置来判断
        return false;
    }
} 